//
//  XDRecorder.m
//  transcoding(MP3)
//
//  Created by xindong on 16/11/12.
//  Copyright © 2016年 xindong. All rights reserved.
//
// lame download:    http://lame.sourceforge.net/download.php
// lame buildScript: https://github.com/kewlbear/lame-ios-build.git

#import "XDRecorder.h"
#import <AVFoundation/AVFoundation.h>
#import "lame.h"

// 采样率
typedef NS_ENUM(NSInteger, AudioSample) {
    AudioSampleRateLow = 8000,
    AudioSampleRateMedium = 44100, //音频CD采样率
    AudioSampleRateHigh = 96000
};


@interface XDRecorder ()
{
    
}

@property (nonatomic, strong) AVAudioRecorder *recorder;
@property (nonatomic, strong) AVAudioSession *audioSession;
@property (nonatomic, strong) NSMutableDictionary *settings;
@property (nonatomic, strong) NSString *originalDataPath;
@property (nonatomic, strong) NSString *mp3DataPath;

@end

@implementation XDRecorder

static inline NSString* GetAudioDirectoryPathWithAudioName(NSString *audioName) {
    NSString *path = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES).lastObject;
    NSString *directoryPath = [path stringByAppendingPathComponent:@"com.wobingwoyi.audio"];
    NSFileManager *manager = [NSFileManager defaultManager];
    BOOL isCreateSuccess = [manager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];
    if (isCreateSuccess) return [directoryPath stringByAppendingPathComponent:audioName];
    return nil;
}

- (NSString *)originalDataPath
{
    if (!_originalDataPath)
    {
        NSString *dateStr = [[WPDateFormatterManager sharedManager] stringFromDateWithDate:[NSDate date] format:@"yyyy-MM-dd-HH:mm:ss"];
        NSString *originalAudioStr = [NSString stringWithFormat:@"originalAudio-%@",dateStr];
        _originalDataPath = GetAudioDirectoryPathWithAudioName(originalAudioStr);
    }
    return _originalDataPath;
}

- (NSString *)mp3DataPath
{
    if (!_mp3DataPath)
    {
        NSString *dateStr = [[WPDateFormatterManager sharedManager] stringFromDateWithDate:[NSDate date] format:@"yyyy-MM-dd-HH:mm:ss"];
        NSString *mp3NameStr = [NSString stringWithFormat:@"translatedAudio-%@.mp3",dateStr];
        _mp3DataPath = GetAudioDirectoryPathWithAudioName(mp3NameStr);
    }
    return _mp3DataPath;
}

- (AVAudioSession *)audioSession
{
    if (_audioSession == nil)
    {
        _audioSession = [AVAudioSession sharedInstance];
        [_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
        
        if ([_audioSession respondsToSelector:@selector(requestRecordPermission:)])
        {
            [_audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted)
            {
                if (granted)
                {
                    NSLog(@"正常录音");
                    [_audioSession setActive:YES error:nil];
                }
                else
                {
                    NSLog(@"失败录音");
                }
            }];
        }
        [_audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
    }
    return _audioSession;
}

- (NSMutableDictionary *)settings
{
    if (_settings == nil)
    {
        _settings = [NSMutableDictionary dictionary];
        [_settings setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
        [_settings setObject:@(AudioSampleRateMedium) forKey:AVSampleRateKey];
        [_settings setObject:@(2) forKey:AVNumberOfChannelsKey]; //双声道
        [_settings setValue:@(16) forKey:AVLinearPCMBitDepthKey];
        [_settings setObject:@(AVAudioQualityHigh) forKey:AVEncoderAudioQualityKey];
    }
    return _settings;
}

-(void)starRecording
{
    [self.recorder record];
    NSString *textValue = [NSString stringWithFormat:@"开始录音：%@", self.originalDataPath];
    NSLog(@"%@", textValue);

}

-(AVAudioRecorder *)recorder
{
    if (_recorder == nil)
    {
        NSError *error = nil;
        _recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:self.originalDataPath] settings:self.settings error:&error];
        _recorder.meteringEnabled = YES;
        [_recorder prepareToRecord];
        if (error)
        {
            NSLog(@"录音失败:%@",error);
        }
    }
    return _recorder;
}

-(void)pauseRecording
{
    [self.recorder pause];
}

-(void)stopRecording
{
    [self.recorder stop];
}

-(void)transcodingToMP3
{
    [self startTranscoding];
}


// 录音结束后一次性转码
- (void)startTranscoding {
    @try {
        int read, write;
        
        FILE *pcm = fopen([self.originalDataPath cStringUsingEncoding:1], "rb");//source
        fseek(pcm, 4*1024, SEEK_CUR);                                           //skip file header
        FILE *mp3 = fopen([self.mp3DataPath cStringUsingEncoding:1], "wb");     //output
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];
        
        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, AudioSampleRateMedium);
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        
        do {
            read = (int)fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }
    @finally {
        NSString *textValue = [NSString stringWithFormat:@"转换成功：%@", self.mp3DataPath];
        NSLog(@"%@", textValue);
        [self excuteDelegateMethod:nil mp3DataPath:self.mp3DataPath];
    }
}


- (void)excuteDelegateMethod:(NSError *)error mp3DataPath:(NSString *)mp3DataPath
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(transcodingToMP3With:mp3DataPath:)])
    {
        [self.delegate transcodingToMP3With:error mp3DataPath:mp3DataPath];
    }
}


@end
